/*
 * The contents of this web application are subject to the Mozilla Public License Version 
 * 1.1 (the "License"); you may not use this web application except in compliance with 
 * the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, 
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
 * for the specific language governing rights and limitations under the License.
 * 
 * The Original Code is owned by and the Initial Developer of the Original Code is 
 * Composite A/S (Danish business reg.no. 21744409). All Rights Reserved
 * 
 * Section 11 of the License is EXPRESSLY amended to include a provision stating 
 * that any dispute, including but not limited to disputes related to the enforcement 
 * of the License, to which Composite A/S as owner of the Original Code, as Initial 
 * Developer or in any other role, becomes a part to shall be governed by Danish law 
 * and be initiated before the Copenhagen City Court ("K�benhavns Byret")            
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Composite.Core.Routing;
using Composite.Core.Types;
using Composite.Data;

namespace Composite.Plugins.Routing.InternalUrlConverters
{
    class DataInternalUrlConverter: IInternalUrlConverter
    {
        private readonly IEnumerable<string> _urlPrefixes;
        private readonly Type _type;
        private readonly Type _keyType;
        private readonly ConstructorInfo _dataReferenceConstructor;


        public DataInternalUrlConverter(string shortTypeName, Type type)
        {
            _urlPrefixes = new[] { shortTypeName + "(" };
            _type = type;
            _keyType = _type.GetKeyProperties().Single().PropertyType;

            _dataReferenceConstructor = typeof(DataReference<>).MakeGenericType(_type).GetConstructor(new[] { typeof(object) });
        }


        public IEnumerable<string> AcceptedUrlPrefixes
        {
            get { return _urlPrefixes; }
        }


        public string ToPublicUrl(string internalDataUrl, UrlSpace urlSpace)
        {
            object keyValue = ExtractKeyValue(internalDataUrl);
            if(keyValue == null) return null;

            var data = DataFacade.TryGetDataByUniqueKey(_type, keyValue);
            if(data == null) return null;

            var pageUrlData = DataUrls.TryGetPageUrlData(data.ToDataReference());
            return pageUrlData != null ? PageUrls.BuildUrl(pageUrlData, UrlKind.Public, urlSpace) : null;
        }


        private object ExtractKeyValue(string internalDataUrl)
        {
            int openBracketIndex = internalDataUrl.IndexOf("(", StringComparison.Ordinal);
            if (openBracketIndex < 0)
            {
                return null;
            }

            int closingBracketOffset = internalDataUrl.IndexOf(")", openBracketIndex + 1, StringComparison.Ordinal);
            if (closingBracketOffset < 0)
            {
                return null;
            }

            string dataIdStr = internalDataUrl.Substring(openBracketIndex + 1, closingBracketOffset - openBracketIndex - 1);

            object keyValue = ValueTypeConverter.Convert(dataIdStr, _keyType);

            if (keyValue == null || (keyValue is Guid && (Guid)keyValue == Guid.Empty))
            {
                return null;
            }

            return keyValue;
        }

        public IDataReference ToDataReference(string internalDataUrl)
        {
            object keyValue = ExtractKeyValue(internalDataUrl);
            if (keyValue == null) return null;

            return (IDataReference)_dataReferenceConstructor.Invoke(new [] { keyValue });
        }
    }
}
